package net.monare.mifss.admin.ui.mod;

import com.vaadin.ui.ComboBox;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.TextField;
import com.vaadin.ui.UI;
import net.monare.mifss.MifssAdminMainUI;
import net.monare.mifss.MifssHolder;
import net.monare.mifss.MifssMessages;
import net.monare.mifss.admin.ui.comp.PropertyListUi;
import net.monare.mifss.admin.ui.valid.EmptyStringValidator;
import net.monare.mifss.admin.ui.valid.StorageModeValidator;
import net.monare.mifss.configurations.pojo.StorageDef;
import net.monare.mifss.configurations.pojo.StorageMode;
import net.monare.mifss.exceptions.StorageServiceException;
import net.monare.mifss.services.StorageService;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import java.util.List;

public class StorageDefUiModule extends FormLayout {

    private static final long serialVersionUID = 4859503728636453433L;
    private Logger logger = Logger.getLogger(StorageDefUiModule.class);


    private TextField storageName;
    private ComboBox storageSetName;
    private TextField chainedToStorageName;
    private TextField dataSourceName;
    private TextField description;
    private ComboBox storageMode;
    private TextField title;
    private PropertyListUi storageProperties;

    private ComboBox transformationHandlerName;

    public StorageDefUiModule() {
        initElements();
    }

    public StorageDefUiModule(StorageDef storageDef) {
        initElements();
        populateElements(storageDef);
    }

    private void initElements() {

        MifssHolder mifssHolder = ((MifssAdminMainUI) UI.getCurrent()).getMifssHolder();

        StorageService storageService = mifssHolder.getStorageService();

        // load UI messages
        String chainedToStorageLabel = MifssMessages.getMessage("label.chained.to.storage");
        String dataSourceNameLabel = MifssMessages.getMessage("label.data.source.name");
        String dbTableNameLabel = MifssMessages.getMessage("label.table.name");
        String storageDescriptionLabel = MifssMessages.getMessage("label.storage.description");
        String storageModeLabel = MifssMessages.getMessage("label.storage.mode");
        String storageTitleLabel = MifssMessages.getMessage("label.storage.title");
        String storageTransformationLabel = MifssMessages.getMessage("label.storage.transformation");
        String stringValidationMsg = MifssMessages.getMessage("validation.empty.string");
        String storageModeValidationMsg = MifssMessages.getMessage("validation.select.storage.mode");
        String storagePropertiesLabel = MifssMessages.getMessage("label.storage.properties");
        String storageNameLabel = MifssMessages.getMessage("label.storage.name");
        String storageSetNameLabel = MifssMessages.getMessage("label.storage.set.name");

        // initialize UI elements
        storageName = new TextField(storageNameLabel);
        storageName.setWidth("90%");

        storageSetName = new ComboBox(storageSetNameLabel);
        storageSetName.setWidth("350px");

        try {

            for (String storageSetNameItem : storageService.listStorageSetNames()) {
                storageSetName.addItem(storageSetNameItem);
            }

        } catch (StorageServiceException x) {
            logger.error(x, x);
            ((MifssAdminMainUI) UI.getCurrent()).error(new com.vaadin.server.ErrorEvent(x));
        }

//        storageSetName.setTextChangeEventMode(AbstractTextField.TextChangeEventMode.EAGER);
//        storageSetName.addListener(new FieldEvents.TextChangeListener() {
//            @Override
//            public void textChange(FieldEvents.TextChangeEvent event) {
//                System.out.println("value changed to: " + event.getText());
//            }
//        });

        chainedToStorageName = new TextField(chainedToStorageLabel);
        chainedToStorageName.setWidth("90%");

        dataSourceName = new TextField(dataSourceNameLabel);
        description = new TextField(storageDescriptionLabel);
        storageMode = new ComboBox(storageModeLabel);

        for (StorageMode m : StorageMode.values()) {
            storageMode.addItem(m);
        }

        title = new TextField(storageTitleLabel);
        title.setWidth("90%");

        transformationHandlerName = new ComboBox(storageTransformationLabel);
        transformationHandlerName.setWidth("350px");

        List<String> listTransformations = storageService.listAvailableTransformations();
        for (String transformationHandlerNameItem : listTransformations) {
            transformationHandlerName.addItem(transformationHandlerNameItem);
        }

        storageProperties = new PropertyListUi(storagePropertiesLabel, "150px", "200px");

        // setup validators
        storageName.addValidator(new EmptyStringValidator(stringValidationMsg));
        storageSetName.addValidator(new EmptyStringValidator(stringValidationMsg));
        dataSourceName.addValidator(new EmptyStringValidator(stringValidationMsg));
        description.addValidator(new EmptyStringValidator(stringValidationMsg));
        storageMode.addValidator(new StorageModeValidator(storageModeValidationMsg));
        title.addValidator(new EmptyStringValidator(stringValidationMsg));

        // add UI elements to form
        addComponent(storageName);
        addComponent(storageSetName);
        addComponent(chainedToStorageName);
        addComponent(dataSourceName);
        addComponent(storageMode);
        addComponent(title);
        addComponent(transformationHandlerName);
        addComponent(description);
        addComponent(storageProperties);

    }

    public StorageDef getStorageDef() {

        StorageDef storageDef;

        try {

            storageDef = new StorageDef();

            if (storageName.isValid()) {
                storageDef.setName(storageName.getValue());
            } else {
                return null;
            }

            if (StringUtils.isNotEmpty(chainedToStorageName.getValue()))
                storageDef.setChainedToStorageName(chainedToStorageName.getValue());


            if (dataSourceName.isValid()) {
                storageDef.setDataSourceName(dataSourceName.getValue());
            } else {
                return null;
            }

            if (description.isValid()) {
                storageDef.setDescription(description.getValue());
            } else {
                return null;
            }

            if (storageMode.isValid()) {
                storageDef.setMode((StorageMode) storageMode.getValue());
            } else {
                return null;
            }

            if (title.isValid()) {
                storageDef.setTitle(title.getValue());
            } else {
                return null;
            }

            if (transformationHandlerName.getValue() != null) {
                if (StringUtils.isNotEmpty(transformationHandlerName.getValue().toString())) {
                    storageDef.setTransformationHandlerName(transformationHandlerName.getValue().toString());
                }
            }

            if (storageProperties.getPropertySet() != null) {
                storageDef.setProperties(storageProperties.getPropertySet());
            }

        } catch (Exception x) {

            // log error
            logger.error(x, x);
            ((MifssAdminMainUI) UI.getCurrent()).error(new com.vaadin.server.ErrorEvent(x));

            storageDef = null;

        }

        return storageDef;
    }

    public void setStorageDef(StorageDef storageDef) {
        populateElements(storageDef);
    }

    public void protectFields() {

        dataSourceName.setEnabled(false);

    }

    private void populateElements(StorageDef storageDef) {

        if (storageDef.isChained()) {
            chainedToStorageName.setValue(storageDef.getChainedToStorageName());
        }

        storageName.setValue(storageDef.getName());
        storageSetName.setValue(storageDef.getStorageSetDef().getName());
        dataSourceName.setValue(storageDef.getDataSourceName());
        description.setValue(storageDef.getDescription());
        storageMode.setValue(storageDef.getMode());
        title.setValue(storageDef.getTitle());

        if (StringUtils.isNotEmpty(storageDef.getTransformationHandlerName())) {
            transformationHandlerName.setValue(storageDef.getTransformationHandlerName());
        }

        if (storageDef.getProperties() != null) {
            storageProperties.setProperties(storageDef.getProperties());
        }

    }

    public String getStorageSetName() {
        return storageSetName.getValue().toString();
    }
}